﻿using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SpyTxT
{  
    class NetClient
    {       
        private IPEndPoint ipep;
        private UdpClient udpc;
        private Thread recvthread;
        private Thread sendthread;
        private TcpClient tcpc;
        private DateTime runrecvtime = DateTime.Now;

        public DateTime Runrecvtime
        {
          get { return runrecvtime; }
          set { runrecvtime = value; }
        }
        private DateTime runsendtime = DateTime.Now;

        public DateTime Runsendtime
        {
          get { return runsendtime; }
          set { runsendtime = value; }
        }
        private bool bRecvRun = true;
        private bool bSendRun = true;

        public bool BSendRun
        {
            get { return bSendRun; }
            set { bSendRun = value; }
        }

        public bool BRecvRun
        {
            get { return bRecvRun; }
            set { bRecvRun = value; }
        }
        private INetError ineterror;
        public SpyTxT.INetError Ineterror
        {
            get { return ineterror; }
            set { ineterror = value; }
        }
        private IDoPack idopack;
        public SpyTxT.IDoPack Idopack
        {
            get { return idopack; }
            set { idopack = value; }
        }
        public enum NetMode{TCP_CLIENT,UDP_CLIENT};
        private ArrayList sendlist = new ArrayList();
        private ArrayList senddatalist = new ArrayList();
        NetMode netmode;
        /*
         * 说明     :初始化网络,并且连接服务器
         * 
         * ip       :服务器IP
         * port     :服务器端口
         * dopack   :接收处理回调
         * netmode  :连接模式
         * 
         */
        public bool InitNet(string ip, int port, NetMode netmode)
        {
            try
            {
                
                this.netmode = netmode;
                ipep = new IPEndPoint(IPAddress.Parse(ip), port);
                if (netmode == NetMode.TCP_CLIENT)
                {
                    tcpc = new TcpClient();
                    tcpc.Connect(ipep);
                }
                else if (netmode == NetMode.UDP_CLIENT)
                {
                    udpc = new UdpClient();
                    udpc.Connect(ipep);
                }

                

                
                

                recvthread = new Thread(new ThreadStart(ClientRecvThread));
                recvthread.Start();

                sendthread = new Thread(new ThreadStart(ClientSendThread));
                sendthread.Start();

                return true;
            }
            catch (System.Exception ex)
            {
                
                System.Console.WriteLine(ex.Message);
                if(this.Ineterror != null)
                    ineterror.INetError(ex);
            }

            return false;


        }
        /*
         * 说明     :网络发送线程
         * 
         */
        private void ClientSendThread()
        {
            bSendRun = true;
            if (this.netmode == NetMode.TCP_CLIENT)
            {
                while (bSendRun)
                {
                    Runsendtime = DateTime.Now;
                    if (sendlist.Count > 0)
                    {
                        Monitor.Enter(sendlist);

                        string data = (string)sendlist[0];

                        byte[] b = Encoding.Default.GetBytes(data);

                        try
                        {
                            if (tcpc.GetStream().CanWrite)
                            {
                                try
                                {
                                    tcpc.GetStream().Write(b, 0, b.Length);

                                    sendlist.RemoveAt(0);
                                }
                                catch (Exception ex)
                                {
                                    System.Diagnostics.Debug.WriteLine(ex.Message);
                                    if (this.Ineterror != null)
                                        ineterror.INetError(ex);
                                    bSendRun = false;
                                  
                                }


                            }
                        }
                        catch (Exception ex)
                        {
                            System.Diagnostics.Debug.WriteLine(ex.Message);
                            if (this.Ineterror != null)
                                ineterror.INetError(ex);

                            bSendRun = false;
                        }

                        Monitor.Exit(sendlist);

                    }

                    if (senddatalist.Count > 0)
                    {
                        Monitor.Enter(senddatalist);

                        byte[] b = (byte[])senddatalist[0];

                        try
                        {
                            if (tcpc.GetStream().CanWrite)
                            {
                                
                                tcpc.GetStream().Write(b, 0, b.Length);
                                senddatalist.RemoveAt(0);

                            }
                        }
                        catch (Exception ex)
                        {
                            System.Diagnostics.Debug.WriteLine(ex.Message);
                            if (this.Ineterror != null)
                                ineterror.INetError(ex);
                        }
                        Monitor.Exit(senddatalist);

                    }

                    Thread.Sleep(1);

                }
               

            }
            else if (this.netmode == NetMode.UDP_CLIENT)
            {
                while (bSendRun)
                {
                    
                    if (sendlist.Count > 0)
                    {
                        Monitor.Enter(sendlist);

                        string data = (string)sendlist[0];

                        byte[] b = Encoding.Default.GetBytes(data);

                        try
                        {
                            udpc.Send(b, b.Length);
                            sendlist.RemoveAt(0);
                        }
                        catch (Exception ex)
                        {
                            System.Diagnostics.Debug.WriteLine(ex.Message);
                            if (this.Ineterror != null)
                                ineterror.INetError(ex);

                            bSendRun = false;
                        }
                       

                        Monitor.Exit(sendlist);

                    }
                    Thread.Sleep(1);

                }

                
            }
            
        }
        /*
         * 说明     : 网络接收线程
         * 
         */
        private void ClientRecvThread()
        {

            BRecvRun = true;
            if (this.netmode == NetMode.TCP_CLIENT)
            {
               
                byte[] recvbuf = new byte[tcpc.ReceiveBufferSize];

                while (BRecvRun)
                {
                    Runrecvtime = DateTime.Now;
                    try
                    {

                        NetworkStream netstream = tcpc.GetStream();
                        if (tcpc.Connected && netstream != null && netstream.CanRead)
                        {

                            int readlen = netstream.Read(recvbuf, 0, (int)tcpc.ReceiveBufferSize);

                            if (readlen > 0)
                                idopack.IDoPackData(recvbuf, readlen);

                            Array.Clear(recvbuf, 0, recvbuf.Length); 
                        }
                        else if (tcpc.Connected == false)
                        {
                            if (this.tcpc != null)
                            {
                                System.Diagnostics.Debug.WriteLine("连接断线");
                                if (this.Ineterror != null)
                                    ineterror.INetError(null);
                            }
                            BRecvRun = false;
                            
                        }
                    }
                    catch (Exception ex)
                    {
                        if (this.tcpc != null)
                        {
                            System.Console.WriteLine("连接异常");
                            System.Console.WriteLine(ex.Message);
                            if (this.Ineterror != null)
                                ineterror.INetError(ex);
                        }

                        BRecvRun = false;

                    }
                }
            }
            else if(this.netmode == NetMode.UDP_CLIENT)
            {
                while (BRecvRun)
                {
                    try
                    {

                        Byte[] receiveBytes = udpc.Receive(ref ipep);

                        idopack.IDoPackData(receiveBytes, receiveBytes.Length);

                    }
                    catch (Exception ex)
                    {
                        if (udpc != null)
                        {
                            System.Diagnostics.Debug.WriteLine(ex.Message);
                            if (this.Ineterror != null)
                                ineterror.INetError(ex);
                        }
                        BRecvRun = false;
                        

                    }

                }
            }
        }
        /*
         * 说明     :发送数据
         * 
         */

        public void  ClientSend(string data)
        {
            if (IsConnect())
            {
                Monitor.Enter(sendlist);

                sendlist.Add(data);

                Monitor.Exit(sendlist);
            }
            
           
        }

        public void ClientSend(byte[] data)
        {
            if (IsConnect())
            {
                Monitor.Enter(sendlist);

                senddatalist.Add(data);

                Monitor.Exit(sendlist);
            }
           

        }
        public bool IsConnect()
        {
            if (this.tcpc != null || this.udpc != null)
                return true;
            else
                return false;
                
        }
        public void CloseClient()
        {
            if (this.netmode == NetMode.TCP_CLIENT && this.tcpc != null)
            {
                this.tcpc.Close();
            }
            else if (this.netmode == NetMode.UDP_CLIENT && udpc != null)
            {
                this.udpc.Close();
            }

            BSendRun = false;
            BRecvRun = false;
            System.Console.WriteLine("CloseClient thread");
  

            
           
            this.tcpc = null;
            this.udpc = null;
            Thread.Sleep(1000);
           

        }
    
    }
}
